#define DEBUG
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn=30, maxs=200000;

class Block {
public:
  int x, y;

  static bool cmp(Block a, Block b) {
    return a.x<b.x || (a.x==b.x && a.y<b.y);
  }
};

void getBlock2(int x, int n, int map[][maxn+1], bool book[][maxn+1], Block *ans);

void getBlock1(int x, int n, int map[][maxn+1], bool book[][maxn+1], Block *ans) {
  book[0][x] = true;
  ans->x++;
  for (int i=1; i<=n; i++) {
    if (map[x][i] && !book[1][i]) {
      getBlock2(i, n, map, book, ans);
    }
  }
}
void getBlock2(int x, int n, int map[][maxn+1], bool book[][maxn+1], Block *ans) {
  ans->y++;
  book[1][x] = true;
  for (int i=1; i<=n; i++) {
    if (map[i][x] && !book[0][i]) {
      getBlock1(i, n, map, book, ans);
    }
  }
}

void reMark(int blocksize, Block *block, int blockMap[][3]) {
  sort(block+1, block+blocksize+1, Block::cmp);

  int t=0;
  for (int i=1; i<=blocksize; i++) {
    if (block[i].x!=block[i-1].x || block[i].y!=block[i-1].y) {
      t++;
      blockMap[t][1] = block[i].x, blockMap[t][2] = block[i].y;
      blockMap[t][0] = 0;
    }
    blockMap[t][0]++;
  }
  blockMap[0][0] = t;
}

void initBlocks(int n, int map[][maxn+1], int blockMap[][3]) {
  int blocksize=0;
  static Block block[maxn+1];
  static bool book[2][maxn+1];
  for (int i=1; i<=n; i++) {
    if (!book[0][i]) {
      getBlock1(i, n, map, book, block+(++blocksize));
    }
  }
  for (int i=1; i<=n; i++) {
    if (!book[1][i]) {
      block[++blocksize].y = 1;
    }
  } 

  reMark(blocksize, block, blockMap);
}

int getS(int blockMap[][3], int *pos) {
  int ret=1;
  for (int i=1; i<=blockMap[0][0]; i++) {
    pos[i] = ret;
    ret = ret*(blockMap[i][0]+1);
  }
  return ret;
}

void calcStatus(int blockMap[][3], int o, int *ans) {
  for (int i=1; i<=blockMap[0][0]; i++) {
    ans[i] = o%(blockMap[i][0]+1);
    o/=blockMap[i][0]+1;
  }
}

int main() {
  freopen("factory.in", "r", stdin);
  freopen("factory.out", "w", stdout);

  static int map[maxn+1][maxn+1];
  static int blockMap[maxn+1][3];
  int n, ans=0;
  scanf("%d", &n);
  for (int i=1; i<=n; i++) {
    for (int j=1; j<=n; j++) {
      scanf("%1d", &map[i][j]);
      ans -= map[i][j];
    }
  }

  initBlocks(n, map, blockMap);
  static int pos[maxn+1];
  int s=getS(blockMap, pos);

  static int f[maxs+1][maxn+1];
  memset(f, 100, sizeof(f));
  f[0][0] = 0;
  for (int i=0; i<s; i++) {
    static int status[maxn+1];
    calcStatus(blockMap, i, status);
    for (int j=n; j>=0; j--) {
      for (int k=1; k<=blockMap[0][0]; k++) {
	if (blockMap[k][0]-status[k] && j+blockMap[k][1]<=n) {
	  f[i+pos[k]][j+blockMap[k][1]] = min(f[i+pos[k]][j+blockMap[k][1]], f[i][j]);
	}
      }

      int sumx=0, sumy=0;
      for (int k=1; k<=blockMap[0][0]; k++) {
	sumx+=status[k]*blockMap[k][1];
	sumy+=status[k]*blockMap[k][2];
      }
      if (sumx==sumy) {
	f[i][0] = min(f[i][0], f[i][j]+j*j);
      }
    }
  }

  ans += f[s-1][0];
  printf("%d", ans);

  fclose(stdin);
  fclose(stdout);
  return 0;
}
